package main

import (
	"encoding/json"
	"expvar"
	"fmt"
	"sync"
	"time"
)

var (
	timeFormat = "2006-01-02 15:04:05"
)

/* 任务执行状态监控 */
type TaskServiceMonitor struct {
	AvgTiming        expvar.Float
	MaxTiming        expvar.Float
	MinTiming        expvar.Float
	RunningTaskCount expvar.Float
	TaskThroughput   expvar.Float // 任务处理速率
}

type MonitorSamples []MonitorSample

func (m MonitorSamples) chunkSlice(chunkSize int) []MonitorSamples {

	slice := m
	numChunks := (len(slice) + chunkSize - 1) / chunkSize
	chunks := make([]MonitorSamples, numChunks)

	for i := 0; i < numChunks; i++ {
		start := i * chunkSize
		end := start + chunkSize

		if end > len(slice) {
			end = len(slice)
		}

		chunks[i] = slice[start:end]
	}

	return chunks
}

type MonitorSample struct {
	Delta float64
	time  time.Time
}

type TimePair struct {
	start time.Time
	end   time.Time
}

type MonitorOutputItem struct {
	Delta    float64
	duration TimePair
}

type MonitorOutput struct {
	Max   float64 `json:"max"`
	Min   float64 `json:"min"`
	Avg   float64 `json:"avg"`
	Count int64   `json:"count"`
	Sum   float64 `json:"sum"`
	Rate  float64 `json:"rate"`
}

func (m MonitorOutput) String() string {

	b, _ := json.Marshal(m)
	return string(b)
}

type Counter struct {
	locker      sync.Mutex
	val         MonitorSamples
	duration    int // 保留多久的数据，单位：秒
	close       chan struct{}
	output      MonitorOutput
	timeConsume int64
}

func NewCounter(duration int) *Counter {

	counter := &Counter{
		duration: duration,
	}

	//go counter.run()
	return counter
}

//func (c *Counter) run() {
//
//	/*
//		1. 创建一个定时器，每隔一秒触发一次
//		2. 每间隔 c.interval 的时间输出一次指标
//	*/
//	ticker := time.NewTicker(time.Second * time.Duration(c.duration))
//	for {
//		select {
//		case <-ticker.C:
//
//		case <-c.close:
//			// 执行清理工作
//			ticker.Stop()
//			return
//		}
//	}
//
//}

func (c *Counter) getByTimePair(tp TimePair) MonitorSamples {

	var (
		start      = tp.start
		startIndex int
		end        = tp.end
		endIndex   int
	)

	for i, v := range c.val {
		if v.time.Before(start) {
			start = v.time
			startIndex = i
		}
		if v.time.After(end) {
			end = v.time
			endIndex = i
		}
	}
	return MonitorSamples{c.val[startIndex], c.val[endIndex]}
}

func (c *Counter) Calculate(duration int) MonitorOutput {

	now := time.Now()

	tp := TimePair{
		start: now.Add(-time.Duration(duration) * time.Second),
		end:   now,
	}

	if len(c.val) == 0 {
		return MonitorOutput{}
	}

	var (
		startIndex int
		endIndex   = len(c.val) - 1

		count int64
		sum   float64
	)

	for i, v := range c.val {
		if v.time.After(tp.start) {
			startIndex = i
			if i > 1 {
				startIndex = i - 1
			}
			break
		}
	}

	min := c.val[startIndex].Delta
	max := c.val[startIndex].Delta
	for _, v := range c.val[startIndex:] {

		if v.Delta < min {
			min = v.Delta
		}
		if v.Delta > max {
			max = v.Delta
		}
		count += 1
		sum += v.Delta
	}

	ms := MonitorSamples{c.val[startIndex], c.val[endIndex]}
	var (
		from = ms[0]
		to   = ms[1]
	)

	rate := MonitorOutputItem{
		Delta: (to.Delta - from.Delta) / float64(to.time.UnixMilli()-from.time.UnixMilli()),
		duration: TimePair{
			start: from.time,
			end:   to.time,
		},
	}

	output := MonitorOutput{
		Rate:  rate.Delta,
		Max:   max,
		Min:   min,
		Count: count,
		Avg:   sum / float64(count),
		Sum:   sum,
	}
	return output
}

func (c *Counter) Inc(data MonitorSample) {

	c.locker.Lock()
	defer c.locker.Unlock()

	data.time = time.Now()
	if len(c.val) > 1 {
		if c.timeConsume > int64(c.duration) {
			c.val = c.val[1:]
		}
		c.timeConsume = data.time.Unix() - c.val[0].time.Unix()
		fmt.Println("时间消耗:", c.timeConsume, "元素个数", len(c.val), "最早的时间:", c.val[0].time, "最早的数值:", c.val[0].Delta, "最晚的时间:", c.val[len(c.val)-1].time, "最晚的数值:", c.val[len(c.val)-1].Delta)
	}
	c.val = append(c.val, data)
}
